#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <3ds.h>

#include <malloc.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <fcntl.h>

#include "text.h"
#include "math.h"


#define print(...) sprintf(&superStr[strlen(superStr)], __VA_ARGS__); drawFrame()
char superStr[8192];

int countLines(char* str)
{
	if(!str)return 0;
	int cnt; for(cnt=1;*str=='\n'?++cnt:*str;str++);
	return cnt;
}

void cutLine(char* str)
{
	if(!str || !*str)return;
	char* str2=str;	for(;*str2&&*(str2+1)&&*str2!='\n';str2++);	str2++;
	memmove(str,str2,strlen(str2)+1);
}

void drawFrame()
{
	u8* bufAdr=gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL);

	memset(bufAdr, 0, 400*240*3);

	u32 ip = gethostid();
	char bof[256];
	sprintf(bof, "IP: %lu.%lu.%lu.%lu, port 5000, press B at any time to exit\n", ip & 0xFF, (ip>>8)&0xFF, (ip>>16)&0xFF, (ip>>24)&0xFF);
	gfxDrawText(GFX_TOP, GFX_LEFT, NULL, bof, 240-fontDefault.height*1, 10);

	int i = countLines(superStr);
	while(i>240/fontDefault.height-1){cutLine(superStr);i--;}
	gfxDrawText(GFX_TOP, GFX_LEFT, NULL, superStr, 240-fontDefault.height*2, 20);

	gfxFlushBuffers();
	gfxSwapBuffers();
}

void printM4x4(float mat[4][4]) {
	print("%f %f %f %f\n",mat[0][0],mat[0][1],mat[0][2],mat[0][3]);
	print("%f %f %f %f\n",mat[1][0],mat[1][1],mat[1][2],mat[1][3]);
	print("%f %f %f %f\n",mat[2][0],mat[2][1],mat[2][2],mat[2][3]);
	print("%f %f %f %f\n",mat[3][0],mat[3][1],mat[3][2],mat[3][3]);
}

void testMatrix()
{
        float m1[4][4];
        float m2[4][4];
        float mat[4][4];
                
        loadIdentity44((float *)m1);
	m1[0][2] = 10.0f;
	m1[1][3] = 3.3f;
	m1[2][0] = 13.7f;
	m1[3][2] = 42.5f;

        loadIdentity44((float *)m2);
	m2[0][2] = 1.0f;
	m2[1][2] = 2.0f;
	m2[2][2] = 3.0f;
	m2[3][2] = 4.0f;

	unsigned long int i;
	for(i=0; i<1000000; i++) {
	        multMatrix44(m1,m2,mat);
	}

	printM4x4(mat);
}

void testMatrixFPU()
{
        float m1[4][4];
        float m2[4][4];
        float mat[4][4];
                
        loadIdentity44((float *)m1);
	m1[0][2] = 10.0f;
	m1[1][3] = 3.3f;
	m1[2][0] = 13.7f;
	m1[3][2] = 42.5f;

        loadIdentity44((float *)m2);
	m2[0][2] = 1.0f;
	m2[1][2] = 2.0f;
	m2[2][2] = 3.0f;
	m2[3][2] = 4.0f;
                
	unsigned long int i;
	for(i=0; i<1000000; i++) {
	        multMatrix44FPU(m1,m2,mat);
	}

	printM4x4(mat);
}

int main()
{
	srvInit();	
	aptInit();
	hidInit(NULL);
	gfxInit();

	gfxSet3D(false);

	superStr[0]=0;

	while(aptMainLoop())
	{
		drawFrame();

		hidScanInput();
		if(hidKeysDown()&KEY_B) break;
		if(hidKeysDown()&KEY_A) testMatrix();
		if(hidKeysDown()&KEY_Y) testMatrixFPU();

		gspWaitForEvent(GSPEVENT_VBlank0, false);
	}

	gfxExit();
	hidExit();
	aptExit();
	srvExit();
	return 0;
}
